import datetime
import os
from selenium.common.exceptions import NoSuchElementException
from selenium import webdriver
from selenium.webdriver import ActionChains
from time import sleep
from operator import methodcaller
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.support.ui import WebDriverWait
import logging

logger = logging.getLogger()


class sele_Util:

    def __init__(self, browser):
        logger.info('======初始化webdriver======')
        try:
            self.driver = None
            # 进行浏览器驱动初始化
            if browser == 'Chrome':
                option = webdriver.ChromeOptions()
                # 关闭“chrome正受到自动测试软件的控制”
                # V75以及以下版本
                # option.add_argument('disable-infobars')
                # V76以及以上版本
                option.add_experimental_option("excludeSwitches", ["ignore-certificate-errors"])
                option.add_experimental_option('useAutomationExtension', False)
                option.add_experimental_option('excludeSwitches', ['enable-automation'])
                # 不自动关闭浏览器
                option.add_experimental_option("detach", True)
                chrome_driver_path = os.path.abspath(r'/usr/local/bin/chromedriver')
                self.driver = webdriver.Chrome(executable_path=chrome_driver_path, chrome_options=option)
            if browser == 'FireFox':
                option = webdriver.FirefoxOptions()
                self.driver = webdriver.Firefox(options=option)

            if browser == 'IE':
                option = webdriver.IeOptions()
                self.driver = webdriver.Ie(options=option)
        except Exception as e:
            logger.error(msg='driver 初始化异常: %s' % str(type(e)) + '::%s' % e)

    # 打开url
    def open(self, url):
        try:
            logger.info('执行 open 方法:    打开' + url)
            self.driver.get(url)
        except Exception as e:
            if type(e) is NoSuchElementException:
                e = e.msg
            logger.error(msg='open 异常:  %s' % str(type(e)) + '::%s' % e)

    # 元素定位
    def locator(self, find_command, name):
        try:
            logger.info('执行 locator 定位: 查询命令=' + find_command + '   路径=' + name)
            return self.driver.find_element(find_command, name)
        except Exception as e:
            if type(e) is NoSuchElementException:
                e = e.msg
            logger.error(msg='locator 异常:   %s' % str(type(e)) + '::%s' % e)
            return None

    # 针对不可直视元素进行点击操作（绑定为第一个，针对下拉框进行点击，建议使用唯一性name进行元素搜索）
    def visibility_click(self, find_command, name):
        try:
            logger.info('执行 visibility_click 方法:    查询命令=' + find_command + '   路径=' + name)
            sleep(1)
            ele = WebDriverWait(self.driver, 5).until(
                expected_conditions.element_to_be_clickable((find_command, name)))
            self.driver.execute_script('arguments[0].scrollIntoView();', ele)
            ele.click()
            sleep(1)
        except Exception as e:
            if type(e) is NoSuchElementException:
                e = e.msg
            logger.error(msg='visibility_click 异常:  %s' % str(type(e)) + '::%s' % e)

    # 获取元素文字内容
    def get_text(self, find_command, name):
        try:
            logger.info('执行 get_text 方法:    查询命令=' + find_command + '   路径=' + name)
            return self.driver.find_element(find_command, name).text
        except Exception as e:
            if type(e) is NoSuchElementException:
                e = e.msg
            logger.error(msg='get_text 异常:%s' % str(type(e)) + '::%s' % e)
            return None

    # 元素点击
    def click(self, find_command, name):
        try:
            logger.info('执行 click 方法:   查询命令=' + find_command + '  路径=' + name)
            sleep(1)
            # action = ActionChains(self.driver)
            # action.click(self.driver.find_element(find_command, name))
            # action.perform()
            ele = self.driver.find_element(find_command, name)
            self.driver.execute_script('arguments[0].click()', ele)
            sleep(1)
        except Exception as e:
            if type(e) is NoSuchElementException:
                e = e.msg
            logger.error(msg='click 异常:%s' % str(type(e)) + '::%s' % e)
        # for request in self.driver.requests:
        #     print(type(request.response.body))
        #     print(str(request.response.body, 'UTF-8'))

    # 元素输入内容
    def input(self, find_command, name, value=None):
        try:
            logger.info('执行 input 方法:   查询命令=' + find_command + '路径=' + name + '   输入值:' + str(value))
            sleep(2)
            self.driver.find_element(find_command, name)
            # self.driver.find_element(find_command, name).clear()
            self.driver.find_element(find_command, name).send_keys(value)
        except Exception as e:
            if type(e) is NoSuchElementException:
                e = e.msg
            logger.error(msg='input 异常: %s' % str(type(e)) + '::%s' % e)

    # 设置元素value属性值
    def input_value(self, find_command, name, value=None):
        try:
            logger.info(
                '执行 input_value 方法: 查询命令=' + find_command + '路径=' + name + ' value的输入值:' + str(value))
            sleep(1)
            elem = self.driver.find_element(find_command, name)
            self.set_attribute(elem=elem, attribute='value', value=value)
        except Exception as e:
            if type(e) is NoSuchElementException:
                e = e.msg
            logger.error(msg='input_value 异常:   %s' % str(type(e)) + '::%s' % e)

    # 长按鼠标
    def click_and_hold(self, find_command, name):
        try:
            logger.info('执行 click_and_hold 方法:  查询命令=' + find_command + '   路径=' + name)
            sleep(1)
            action = ActionChains(self.driver)
            action.click_and_hold(self.driver.find_element(find_command, name))
        except Exception as e:
            if type(e) is NoSuchElementException:
                e = e.msg
            logger.error(msg='click_and_hold 异常:    %s' % str(type(e)) + '::%s' % e)

    # 移动
    def move_by_offset(self, find_command, name, value='0,0'):
        try:
            position = value.split(',')
            logger.info('执行 move_by_offset 方法:  查询命令=' + find_command + ' 路径=' + name + '  X轴位移:' + position[0]
                        + 'Y轴位移:' + position[1])
            sleep(1)
            action = ActionChains(self.driver)
            action.click_and_hold(self.driver.find_element(find_command, name))
            action.move_by_offset(position[0], position[1])
            action.release(self.driver.find_element(find_command, name))
            action.perform()
        except Exception as e:
            if type(e) is NoSuchElementException:
                e = e.msg
            logger.error(msg='move_by_offset 异常:    %s' % str(type(e)) + '::%s' % e)

    # 松开鼠标
    def release(self, find_command, name):
        try:
            logger.info('执行 release 方法: 查询命令=' + find_command + '   路径=' + name)
            sleep(1)
            action = ActionChains(self.driver)
            action.release(self.driver.find_element(find_command, name))
        except Exception as e:
            if type(e) is NoSuchElementException:
                e = e.msg
            logger.error(msg='release 异常:   %s' % str(type(e)) + '::%s' % e)

    # 退出
    def quit(self):
        try:
            logger.info('执行 quit 方法')
            self.driver.quit()
        except Exception as e:
            logger.error(msg='quit 异常:  %s' % str(type(e)) + '::%s' % e)

    # selenium js执行器
    def js_execute(self, name):
        try:
            logger.info('执行 js_execute 方法:  JS代码=' + name)
            sleep(1)
            print(self.driver.execute_script(name))
        except Exception as e:
            logger.error(msg='js_execute 异常:    %s' % str(type(e)) + '::%s' % e)

    def remove_attribute(self, elem, attribute):
        try:
            logger.info('执行 remove_attribute 方法: 删除' + elem + '的' + attribute)
            sleep(1)
            print(self.driver.execute_script('arguments[0].removeAttribute(arguments[1])', elem, attribute))
        except Exception as e:
            logger.error(msg='remove_attribute 异常:  %s' % str(type(e)) + '::%s' % e)

    def set_attribute(self, elem, attribute, value):
        logger.info('执行 set_attribute 方法:   为' + str(elem) + '添加' + attribute + '属性，值为：' + value)
        self.driver.execute_script('arguments[0].setAttribute(arguments[1],arguments[2])', elem, attribute, value)

    def methodcaller(self, method_name, **kwargs):
        try:
            for key in list(kwargs.keys()):
                if kwargs[key] is None:
                    del kwargs[key]
        except Exception as e:
            logger.error(msg='methodcaller 异常:  %s' % str(type(e)) + '::%s' % e)
        finally:
            caller = methodcaller(str(method_name), **kwargs)
            caller(self)

    def screenshot(self):
        png = self.driver.get_screenshot_as_png()
        return png
